-- Decompiled with the Synapse X Luau decompiler.

--回调函数管理器
local RunService = game:GetService("RunService");
local CommonOHOH = _G.CommonOHOH;
local Timer = CommonOHOH.load.Timer();
local M = CommonOHOH.class.new(script);
local CO_OBJ = {};
local OBJ_CO_TYPE = {};
local function CoroutineResume(co, dt)
	local obj = CO_OBJ[co];
	if obj and OBJ_CO_TYPE[obj][co] then
		coroutine.resume(co, dt);
	end;
end;
--清除协程数据
local function ClearCoroutine(co)
	local obj = CO_OBJ[co];
	if obj then
		CO_OBJ[co] = nil;
		local objInfo = OBJ_CO_TYPE[obj];
		if objInfo then
			objInfo[co] = nil;
			if not next(objInfo) then
				OBJ_CO_TYPE[obj] = nil;
			end;
		end;
	end;
end;
local function GetFrameTypeByCo(co)
	local data = nil;
	local obj = CO_OBJ[co];
	if obj then
		if not obj:IsExist() then
			return;
		end;
		data = OBJ_CO_TYPE[obj];
		if not data then
			return;
		end;
	else
		return;
	end;
	return data[co];
end;
local FrameUpdate = {};
local TimerData = {
	logic = Timer.new(CoroutineResume), 
	step = Timer.new(CoroutineResume), 
	heart_beat = Timer.new(CoroutineResume)
};
local FrameUpdateBuffer = {};
function FrameUpdate.logic()
	FrameUpdateBuffer.logic = true;
	local v12, v13 = coroutine.resume((coroutine.create(function()
		while true do
			wait();
			if not TimerData.logic:CheckTimeOut() then
				break;
			end;		
		end;
		FrameUpdateBuffer.logic = nil;
	end)));
	if not v12 then
		warn(v13);
	end;
end;
function FrameUpdate.step()
	local u13 = nil;
	u13 = RunService.Stepped:Connect(function()
		if not TimerData.step:CheckTimeOut() then
			u13:Disconnect();
			FrameUpdateBuffer.step = nil;
		end;
	end);
	FrameUpdateBuffer.step = true;
end;
function FrameUpdate.heart_beat()
	local u15 = nil;
	u15 = RunService.Heartbeat:Connect(function()
		if not TimerData.heart_beat:CheckTimeOut() then
			u15:Disconnect();
			FrameUpdateBuffer.heart_beat = nil;
		end;
	end);
	FrameUpdateBuffer.heart_beat = true;
end;
if RunService:IsClient() then
	TimerData.render = Timer.new(CoroutineResume);
	TimerData.first = Timer.new(CoroutineResume);
	TimerData.input = Timer.new(CoroutineResume);
	TimerData.camera = Timer.new(CoroutineResume);
	TimerData.character = Timer.new(CoroutineResume);
	TimerData.last = Timer.new(CoroutineResume);
	function FrameUpdate.render()
		local u17 = nil;
		u17 = RunService.RenderStepped:Connect(function()
			if not TimerData.render:CheckTimeOut() then
				u17:Disconnect();
				FrameUpdateBuffer.render = nil;
			end;
		end);
		FrameUpdateBuffer.render = true;
	end;
	function FrameUpdate.first()
		RunService:BindToRenderStep("OHOH_first", Enum.RenderPriority.First.Value, function()
			if not TimerData.first:CheckTimeOut() then
				RunService:UnbindFromRenderStep("OHOH_first");
				FrameUpdateBuffer.first = nil;
			end;
		end);
		FrameUpdateBuffer.first = true;
	end;
	function FrameUpdate.input()
		RunService:BindToRenderStep("OHOH_input", Enum.RenderPriority.Input.Value, function()
			if not TimerData.input:CheckTimeOut() then
				RunService:UnbindFromRenderStep("OHOH_input");
				FrameUpdateBuffer.input = nil;
			end;
		end);
		FrameUpdateBuffer.input = true;
	end;
	function FrameUpdate.camera()
		RunService:BindToRenderStep("OHOH_camera", Enum.RenderPriority.Camera.Value, function()
			if not TimerData.camera:CheckTimeOut() then
				RunService:UnbindFromRenderStep("OHOH_camera");
				FrameUpdateBuffer.camera = nil;
			end;
		end);
		FrameUpdateBuffer.camera = true;
	end;
	function FrameUpdate.character()
		RunService:BindToRenderStep("OHOH_character", Enum.RenderPriority.Character.Value, function()
			if not TimerData.character:CheckTimeOut() then
				RunService:UnbindFromRenderStep("OHOH_character");
				FrameUpdateBuffer.character = nil;
			end;
		end);
		FrameUpdateBuffer.character = true;
	end;
	function FrameUpdate.last()
		RunService:BindToRenderStep("OHOH_last", Enum.RenderPriority.Last.Value, function()
			if not TimerData.last:CheckTimeOut() then
				RunService:UnbindFromRenderStep("OHOH_last");
				FrameUpdateBuffer.last = nil;
			end;
		end);
		FrameUpdateBuffer.last = true;
	end;
end;
local ObjectManager = CommonOHOH.load.ObjectManager();
function M.Wait(self, obj, t)
	
	if not ObjectManager:IsObjectExsit(obj) then --不存在对象协程结束
		coroutine.yield();
	end;
	
	local co = coroutine.running(); --获取正在运行协程
	if not GetFrameTypeByCo(co) then  --获取帧类型(不存在)
		coroutine.yield();
	end;
	
	local objInfo = OBJ_CO_TYPE[obj]; --获取对象帧数据
	local frameType = nil; --帧类型
	if objInfo then
		frameType = objInfo[co]; --frameType
	end;
	
	local ter = nil; --倒计时
	
	if frameType then
		ter = TimerData[frameType];
	end;
	
	if not ter then

		if not ObjectManager:IsObjectExsit(obj) then --不存在对象协程结束
			coroutine.yield();
		end;
		return wait(t);
	end;
	
	ter:Add(co, t);
	
	if not FrameUpdateBuffer[frameType] then
		FrameUpdate[frameType]();
	end;

	return coroutine.yield() 
end;

-- 每隔一段时间更新
local function Update(co, frameType, object, fuc, time, ...)
	local sumTime = 0;
	while true do
		local t = M:Wait(object, time);
		local v27 = os.clock(); --返回一个程序使用CPU时间的一个近似值。
		sumTime = sumTime + t;
		local success, result = xpcall(fuc, debug.traceback, object, t, sumTime, ...);
		if not success then
			warn(result);
			break;
		end;
		if result == true then
			break;
		end;
		if not  (co) then
			warn("co is delected from " .. object.class, "\n" .. debug.traceback(coroutine.running()));
			break;
		end;	
	end;
	ClearCoroutine(co);
	wait();
end;

--开始协程
local function Process(self, frameType, obj, fuc, ...)
	
	M:Wait(obj);
	if not GetFrameTypeByCo(self) then
		warn("co is delected from " .. obj.class, "\n" .. debug.traceback(coroutine.running()));
		return;
	end;
		
	--执行协程函数
	local s, info = xpcall(fuc, debug.traceback, obj, ...);
	if not s then
		warn(info .. debug.traceback(self));
	end;
	ClearCoroutine(self);
	wait();
end;
local OHOHConnection = CommonOHOH.load.OHOHConnection();
local function ClearCo(p12, p13)
	
	ClearCoroutine(p13);
end;
local function SelfGetFrameType(p14, p15)
	return GetFrameTypeByCo(p15);
end;
function M.AddProcess(self, frameType, object, fuc, ...)
	--参数合法性判断
	assert(frameType, "param co type is nil" .. debug.traceback(coroutine.running()));
	assert(object, "param object is nil" .. debug.traceback(coroutine.running()));
	assert(fuc, "param func is nil" .. debug.traceback(coroutine.running()));
	assert(ObjectManager:IsObjectExsit(object), "object is dtor!", debug.traceback(coroutine.running()));
	
	--创建缓存协程信息
	local proc = coroutine.create(Process);
	OBJ_CO_TYPE[object] = OBJ_CO_TYPE[object] or {};
	OBJ_CO_TYPE[object][proc] = frameType;
	CO_OBJ[proc] = object;
	
	--创建监听，运行协程
	local connect = OHOHConnection.new(object, ClearCo, SelfGetFrameType, proc);
	local success, result = coroutine.resume(proc, proc, frameType, object, fuc, ...);
	if not success then --执行失败
		warn(result .. debug.traceback(coroutine.running()));
		ClearCoroutine(proc);
	end;
	if not FrameUpdateBuffer[frameType] then --运行游戏帧
		FrameUpdate[frameType]();
	end;
	return connect;
end;


function M.AddUpdate(self,frameType,object,fuc,time, ...)
	--参数合法性判断
	assert(frameType, "param co type is nil" .. debug.traceback(coroutine.running()));
	assert(object, "param object is nil" .. debug.traceback(coroutine.running()));
	assert(fuc, "param func is nil" .. debug.traceback(coroutine.running()));
	assert(ObjectManager:IsObjectExsit(object), "object " .. object.class .. " is dtor!" .. debug.traceback(coroutine.running()));
	
	--创建缓存协程信息
	local up = coroutine.create(Update);
	OBJ_CO_TYPE[object] = OBJ_CO_TYPE[object] or {};
	OBJ_CO_TYPE[object][up] =frameType;
	CO_OBJ[up] = object;
	
	--创建监听，运行协程
	local connect = OHOHConnection.new(object, ClearCo, SelfGetFrameType, up);
	local a, b = coroutine.resume(up,up,frameType,object,fuc,time, ...);
	if not a then
		warn(b .. debug.traceback(coroutine.running()));
		ClearCoroutine(up);
	end;
	if not FrameUpdateBuffer[frameType] then
		FrameUpdate[frameType]();
	end;
	return connect;
end;
local CON_INFO = {};
local function Del_Fuc(obj, con)
	local obj_con_data = CON_INFO[obj];
	if obj_con_data then
		obj_con_data[con] = nil;
		if not obj_con_data then
			CON_INFO[obj] = nil;
		end;
	end;
	con:Disconnect();
end;
local function Check_Fun(p32, p33)
	return p33.Connected;
end;
function M.AddRbxConnect(self, obj, signal, fuc)
	assert(obj, "param object is nil");
	assert(signal, "param rbx signal is nil");
	assert(fuc, "param call back is nil");
	local con = signal:Connect(function(...)
		if not ObjectManager:IsObjectExsit(obj) then
			return;
		end;
		return fuc(obj, ...);
	end);
	CON_INFO[obj] = CON_INFO[obj] or {};
	CON_INFO[obj][con] = true;
	return OHOHConnection.new(obj, Del_Fuc, Check_Fun, con);
end;
function M.CancelRbxConnect(self, p39)
	if not p39 then
		return;
	end;
	p39:Disconnect();
end;

function M.DelObject(p40, p41)
	local Timer5 = OBJ_CO_TYPE[p41];
	if Timer5 then
		for Timer6, Timer7 in pairs(Timer5) do
			CO_OBJ[Timer6] = nil;
		end;
		OBJ_CO_TYPE[p41] = nil;
	end;
	local Timer8 = CON_INFO[p41];
	if Timer8 then
		for Timer9, M0 in pairs(Timer8) do
			Timer9:Disconnect();
		end;
		CON_INFO[p41] = nil;
	end;
end;
function M.AddCo(p42, p43, p44, p45)
	assert(p43, "param object is nil");
	assert(ObjectManager:IsObjectExsit(p43), "object is dtor!" .. debug.traceback(coroutine.running()));
	p45 = p45 or coroutine.running();
	OBJ_CO_TYPE[p43] = OBJ_CO_TYPE[p43] or {};
	OBJ_CO_TYPE[p43][p45] = p44;
	CO_OBJ[p45] = p43;
	if not FrameUpdateBuffer[p44] then
		FrameUpdate[p44]();
	end;
	return OHOHConnection.new(p43, ClearCo, SelfGetFrameType, p45);
end;
function M.CoCheck(p46, p47, p48)
	p48 = p48 or coroutine.running();
	if not ObjectManager:IsObjectExsit(p47) then
		coroutine.yield();
	end;
	if not GetFrameTypeByCo(p48) then
		coroutine.yield();
	end;
end;
function M.GetObjectCo(p49)
	return OBJ_CO_TYPE;
end;
function M.GetCoObject(p50)
	return CO_OBJ;
end;
return M;
